<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>http://javascript.ruanyifeng.com/stdlib/attributes.html</title>
</head>
<body>

<p>
    JavaScript提供了一个内部数据结构，用来描述一个对象的属性的行为，控制它的行为。这被称为“属性描述对象”（attributes object）。每个属性都有自己对应的属性描述对象，保存该属性的一些元信息。
</p>
<pre>
    {
        value: 123,
        writable: false,
        enumerable: true,
        configurable: false,
        get: undefined,
        set: undefined
    }

（1）value

value存放该属性的属性值，默认为undefined。

（2）writable

writable存放一个布尔值，表示属性值（value）是否可改变，默认为true。

（3）enumerable

enumerable存放一个布尔值，表示该属性是否可枚举，默认为true。如果设为false，会使得某些操作（比如for...in循环、Object.keys()）跳过该属性。

（4）configurable

configurable存放一个布尔值，表示“可配置性”，默认为true。如果设为false，将阻止某些操作改写该属性，比如，无法删除该属性，也不得改变该属性的属性描述对象（value属性除外）。也就是说，configurable属性控制了属性描述对象的可写性。

（5）get

get存放一个函数，表示该属性的取值函数（getter），默认为undefined。

（6）set

set存放一个函数，表示该属性的存值函数（setter），默认为undefined。
    </pre>

</body>
</html>
<script>
    var o = {
        name: 'haha',
        age: 20
    };
    //    Object.getOwnPropertyDescriptor方法可以读出对象自身属性的属性描述对象。
    console.log(Object.getOwnPropertyDescriptor(o, 'name'));
    console.log(Object.getOwnPropertyDescriptor(o, 'age'));

    //    Object.defineProperty方法允许通过定义属性描述对象，来定义或修改一个属性，然后返回修改后的对象。它的格式如下。
    var o2 = Object.defineProperty({}, 'name', {
        value: 'zhangrxiang',
        writable: true,
        configurable: true,
        enumerable: true,
//        get:function () {
//            return this.value
//        },
//        set:function (name) {
//            this.name = name
//        }
    });
    console.log(o2.name);
    o2.name = "zing";
    console.log(o2.name);


    var o3 = Object.defineProperties({}, {
        p1: {value: 123, enumerable: true},
        p2: {value: 'abc', enumerable: true},
        p3: {
            get: function () {
                return this.p1 + this.p2
            },
            enumerable: true,
            configurable: true
        }
    });
    console.log(o3);
//    上面代码中的p3属性，定义了取值函数get。这时需要注意的是，一旦定义了取值函数get（或存值函数set），就不能将writable设为true，或者同时定义value属性，会报错。


//    属性描述对象的属性，被称为“元属性”，因为它可以看作是控制属性的属性。
//    如果一个属性的enumerable为false，下面三个操作不会取到该属性。
//    for..in循环
//    Object.keys方法
//    JSON.stringify方法


//    可配置性（configurable）决定了是否可以修改属性描述对象。也就是说，当configurable为false的时候，value、writable、enumerable和configurable都不能被修改了。





</script>